/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once


#include "intern/解算器/physics_解算器基类.h"
#include "S_Object.h"
//#define DEF_默认物理 E_物理引擎::E_物理引擎_NewTon
//#define DEF_默认物理 E_物理引擎::E_物理引擎_Chrono
//#define DEF_默认物理 E_物理引擎::E_物理引擎_PhysX
#define DEF_默认物理 E_物理引擎::E_物理引擎_PBF







S_物理解算器* f_创建物理解算器(uint32 id);
S_Physics* f_phy_创建创建解算器(E_物理引擎 type, vec3 域大小);

void f_销毁物理解算器(uint32 id);
void f_phy_销毁物理解算器(S_Physics* phy);
void f_phy_重置(S_Physics* phy, const std::string& path);
void f_phy_重置(S_Physics* phy);

void f_phy_步进解算(S_Physics* phy);

uint32 f_phy_get解算器域分辨率(S_Physics* phy);
uint32 f_物理解算器名词是否存在(uint32 key);

void f_Phy_构建静态网格碰撞划分(S_Physics* phy, float32 最小单元大小);


S_物理材质* f_创建材质(S_物理解算器* 解算器, float32 静摩擦, float32 动摩擦, float32 恢复系数, E_物理引擎 物理引擎 = DEF_默认物理);

S_物理几何体* f_创建平面几何体(S_物理解算器* 解算器, const vec4& v, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理几何体* f_创建方体几何体(S_物理解算器* 解算器, const vec3& v, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理几何体* f_创建球体几何体(S_物理解算器* 解算器, const float32 v, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理几何体* f_创建凸壳物理包围几何(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理几何体* f_创建网格物理几何体(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理几何体* f_创建静态网格物理包围几何(S_物理解算器* 解算器, const S_三角Mesh mesh, E_物理引擎 物理引擎 = DEF_默认物理);

void f_Phy_创建物理几何体(E_物理引擎 物理引擎, S_物理几何体* 几何体);
std::vector<S_物理体*> f_phy_get物理体(S_Physics* phy, E_物理碰撞几何类型 几何类型);
void f_Phy_内部网格填充绑定物体(S_Physics* phy, std::vector<S_物理体*>& Body);

uint32	f_phy_get肌腱数量(S_Physics* phy);
void	f_phy_构建肌腱物体可视(S_Physics* phy, S_物体* Body);
void	f_phy_set肌腱力度(S_Physics* phy, float32* 力度, int32 id);

/*淘汰*/
S_物理体* f_创建物理平面(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, E_物理引擎 物理引擎 = DEF_默认物理);





S_物理体* f_创建静态碰撞(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
S_物理体* f_创建刚体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t, float32 重量 = 1.0);
S_物理体* f_创建控制物理体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
S_物理体* f_创建物理边界(S_物理解算器* 解算器, vec3 size, const S_Tranform& t, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理体* f_Phy_create刚体(S_Physics* phy, S_物理材质* 材质);
S_物理体* f_Phy_create刚体(S_Physics* phy, S_物理几何体& geom, S_物理材质* 材质);
S_物理体* f_Phy_create物理体(S_物理几何体& geom, S_物理材质* 材质, E_物理引擎 phy_type);
S_物理体* f_Phy_create粒子发射(S_Physics* phy, uint32 粒子数, S_物理材质* 材质 = nullptr);
//S_PBF粒子发射* f_Phy_create粒子发射(S_Physics* phy, S_物理体* body);


S_物理体* f_创建物理车轮(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_车轮参数& 属性);
S_物理体* f_创建物理车辆(S_物理解算器* 解算器, S_车体参数& 车体参数 );

void	f_Phy_创建流体(S_Physics* phy, S_物理体* body);
void	f_Phy_销毁物理体(S_物理体* body);

void	f_车辆物理体绑定物体(S_物理解算器* 解算器, S_物理体* 车, std::vector<void*>& 车体);


/*void f_创建车(	S_物理解算器* 解算器, 
				S_物体* 车体, 
				const S_车体参数& 车体参数, 
				vector<S_物体*> 车轮, 
				const vector<S_车轮参数>& 车轮参数, 
				const S_三角Mesh& 车体mesh
);*/
void f_Phy_set肌腱力度(S_Physics* phy, float32* value, int32 num);
void f_Phy_应用力(S_Physics* 解算器, const S_物理互交参数& 互交);


S_物理体*	f_create流体粒子(S_物理解算器* 解算器, S_物理材质& mat, const S_Tranform& t, uint32 num, E_物理引擎 物理引擎 = DEF_默认物理);
S_物理体*	f_create布料(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
S_物理体*	f_create柔体(S_物理解算器* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t);
S_物理体*	f_Phy_create流体(S_Physics* 解算器, S_物理几何体& geom, S_物理材质& mat, const S_Tranform& t, E_物理引擎 物理引擎);
//S_物理体*	f_Phy_create刚体(const S_Tranform& t, float32 重量 = 1.0);

bool		f_Phy_切换物理体类型(E_物理引擎 IdType, S_物理体* body, E_物理体类型 类型);
void		f_Phy_重置发射源(S_物理体* body);
S_体素*		f_Phy_get发射源体素(S_物理体* body);
S_域区*		f_Phy_get域属性(S_Physics* phy);
uint64		f_Phy_get粒子数量(S_Physics* phy);
float32		f_Phy_get粒子大小(S_Physics* phy);

void		f_Phy_get域中粒子(S_Physics* phy, const vec3& coord, std::vector<vec3>& particle);
uvec2		f_Phy_get粒子区间(S_物理体* body);
uvec4		f_Phy_get粒子发射区间(S_物理体* body, float32 速率);
uint64		f_Phy_get发射总数(S_物理体* body);


void f_物理体添加到引擎(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);
void f_物理体从引擎移除(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);
bool f_Phy_物理体添加到引擎(S_Physics* phy, S_物理体* body);
void	f_Phy_add静态碰撞网格(S_Physics* phy, std::vector<vec3>& vert, std::vector<uvec3>& index);

void f_物理体添加碰撞回调(S_物理解算器* 解算器, S_物理体* body, uint32 sceneKey, E_物理引擎 物理引擎 = DEF_默认物理);

//void	f_取碰撞物体(S_物理解算器* 解算器, std::vector<S_物理体>& objs, uint32 scenekey, E_物理引擎 物理引擎 = E_物理引擎::E_物理引擎_Bullet);
//void	f_创建车辆(S_Object* 车身, );

车辆容器_t f_get车辆(S_物理解算器* 解算器, E_物理引擎 物理引擎 = DEF_默认物理);


void f_施加力(S_物理解算器* 解算器, S_物理体* body, const vec3& 力, E_物理引擎 物理引擎 = DEF_默认物理);


void	f_Phy_设置粒子数量(S_物理解算器* 解算器, S_物理体* body, uint32 num, E_物理引擎 物理引擎 = DEF_默认物理);
void	f_Phy_拷贝粒子坐标(S_物理解算器* 解算器, S_物理体* body, vec3* c, E_物理引擎 物理引擎 = DEF_默认物理);
void	f_Phy_拷贝粒子速度(S_物理解算器* 解算器, S_物理体* body, vec3* c, E_物理引擎 物理引擎 = DEF_默认物理);

vec3*	f_Phy_映射粒子坐标(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);
vec3*	f_Phy_映射粒子速度(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);
vec3*	f_Phy_映射粒子外力(S_物理解算器* 解算器, S_物理体* body, E_物理引擎 物理引擎 = DEF_默认物理);




void	f_Phy_set解算器域分辨率(S_Physics* phy, E_物理引擎 type, uint32 分辨率, vec3 世界大小, float32 单元间隔);
void	f_Phy_set解算器域分辨率(S_Physics* phy, float32 分辨率);
void	f_Phy_set解算器域(S_Physics* phy, const vec3& 域大小, const vec3& 域偏移, float32 单元大小);
void	f_Phy_set流体密度(S_Physics* 解算器, S_物理体* body);
void	f_Phy_set流体速度(S_Physics* 解算器, S_物理体* body);
void	f_Phy_set粒子发射(S_物理体* e, std::vector<S_VN>& vn);
void	f_Phy_set粒子发射最大数量(S_物理体* e, uint64 num);
void	f_Phy_set流体飞溅粒子数量(S_Physics* 解算器, uint32 num);
void	f_Phy_set粒子区间(S_物理体* body, const uvec2& 区间, uint64 全局偏移);
void	f_Phy_添加物理体(S_Physics* 解算器, std::vector<S_物理体*>& body);

void	f_Phy_取流体调试数据(S_Physics* 解算器, void* data);
void	f_Phy_取体素调试数据(S_Physics* 解算器, std::vector<vec4>& data);
void	f_Phy_get静态碰撞空间树调试数据(const S_Physics* 解算器, std::vector<vec4>& data, bool 不包含空单元 = true);




